package com.hamilton.erik.pt.mobile.android;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.json.JSONArray;

import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.TextView;

import com.android.volley.Response;
import com.hamilton.erik.pt.core.model.Animal;
import com.hamilton.erik.pt.mobile.android.volley.response.error.listener.DisplayErrorErrorListener;
import com.hamilton.erik.pt.mobile.android.widget.AnimalListAdapter;
import com.hamilton.erik.pt.mobile.client.VolleyJsonRestClient;
import com.hamilton.erik.pt.mobile.util.JsonUtil;
import com.hamilton.erik.pt.mobile.util.ResultUtil;
import com.hamilton.erik.pt.mobile.util.ServerUtil;

public class AnimalListActivity extends ListActivity {
	
	private String userName = null;
	private List<Animal> animals = null;
	private ProgressDialog progressDialog = null;
	
	private final int VIEW_ANIMAL_ACTIVITY = 0;
	private final int ADD_ANIMAL_ACTIVITY = 1;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_animal_list);

		userName = getIntent()
						.getStringExtra(getString(R.string.extra_user_name));

		findViewById(R.id.animal_list_view_add_animal_button).setOnClickListener(
				new View.OnClickListener() {
					@Override
					public void onClick(View view) {
						add();
					}
				});
		
		((TextView)findViewById(R.id.animal_list_view_username_label)).setText(userName + "'s Animals");
		
		createSortBySpinnerDropBox();
		createList();
	}
	
	@Override
	protected void onRestoreInstanceState(Bundle savedInstanceState) {
		if(TextUtils.isEmpty(userName)) {
			userName = savedInstanceState.getString(
					getString(R.string.extra_user_name));
			
			createSortBySpinnerDropBox();
			createList();
		}
	}

	private void createSortBySpinnerDropBox() {
		String[] options = new String[]{
				getString(R.string.sort_by_name_option),
				getString(R.string.sort_by_type_option),
				getString(R.string.sort_by_genus_species_option)};
		ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, options);

		Spinner dropdown = (Spinner)findViewById(R.id.sort_by_drop_down);
		dropdown.setAdapter(adapter);
		
		dropdown.setOnItemSelectedListener(new OnItemSelectedListener() {

			// The onItemSelected(...) method is called when the spinner is initializing.
			// However, this causes an issue on screen rotation... the method is called on
			// initialization, not an actual user selection. This was throwing a NullPointerException
			// when trying to get the text from the selected TextView.  The solution is to ignore the
			// first time, since this will occur long before a user can even physically make a selection:
			//    http://stackoverflow.com/questions/5624825/spinner-onitemselected-executes-when-it-is-not-suppose-to/5918177#5918177
			private int onItemSelectedCalledCount = 0;
			private final int ON_ITEM_SELECTED_CALLED_ON_INIT = 1;
			
			@Override
			public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
				
				// See note above onItemSelectedCalledCount Declaration for why this
				// if statement exists
				if(onItemSelectedCalledCount < ON_ITEM_SELECTED_CALLED_ON_INIT) {
					onItemSelectedCalledCount++;
				}
				else {
					String selectedOption = ((TextView)view).getText().toString();
					
					sortAnimals(selectedOption);					
					populateList();
				}
			}

			@Override
			public void onNothingSelected(AdapterView<?> parent) {
				// Do nothing
			}
			
		});
	}
	
	protected void createList() {
		// Note the retrieveAnimals will populate the list on success.
		// This is done because if the retrieve isn't completed by the
		// time the populate is called, we will have a null pointer.
		// We must wait for the retrieval to be successful before continuing.
		if(animals == null) {
			retrieveList();	
		}
		else {
			populateList();
		}
		
		
		ListView listView = (ListView)findViewById(R.id.animal_list_view);
		listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
			  @Override
			  public void onItemClick(AdapterView<?> parent, final View view,
			    int position, long id) {
				  view(parent.getItemAtPosition(position));
			  }
			});
	}
	
	protected void retrieveList() {
		StringBuilder url = new StringBuilder(ServerUtil.getInstance().buildAnimalPath());
		url.append("/retrieve/all/").append(userName);
		
		if (progressDialog == null) {
	        progressDialog = new ProgressDialog(this);
	        progressDialog.setTitle(getString(R.string.progress_loading_title));
	        progressDialog.setMessage(getString(R.string.animal_list_progress_retrieving_animals));
	    }
	    progressDialog.show();
		
		VolleyJsonRestClient.getClient().getJsonArray(url.toString(),
								new RetrieveAnimalListSuccessListener(),
								new DisplayErrorErrorListener(this, progressDialog));
	}
	
	private class RetrieveAnimalListSuccessListener
							implements Response.Listener<JSONArray> {

		@Override
		public void onResponse(JSONArray response) {
			animals = new ArrayList<Animal>();
			if(response != null) {
				try {
					for(int i = 0; i < response.length(); i++) {
						animals.add(
								JsonUtil.getInstance()
									.getAnimal(response.getJSONObject(i)));
					}
					
					sortAnimals(getString(R.string.sort_by_name_option));
					
					populateList();
					
					if(progressDialog != null && progressDialog.isShowing()) {
						progressDialog.dismiss();
					}
				} catch (Exception e) {
					Log.e("AnimalListActivity",
							String.format("%s: %s","Failed to convert JSONObject to Animal.", e.getMessage()));
				}
			}
		}
	}	
	
	public void sortAnimals(String sortKey) {
		if(sortKey.equals(getString(R.string.sort_by_name_option))) {
			Collections.sort(animals, Animal.NameTypeGenusSpeciesComparator);
		}
		else if(sortKey.equals(getString(R.string.sort_by_type_option))) {
			Collections.sort(animals, Animal.TypeNameGenusSpeciesComparator);
		}
		else if(sortKey.equals(getString(R.string.sort_by_genus_species_option))) {
			Collections.sort(animals, Animal.GenusSpeciesNameTypeComparator);
		}
	}

	protected void populateList() {
		AnimalListAdapter adapter = new AnimalListAdapter(this, animals);
		
		ListView listView = (ListView)findViewById(R.id.animal_list_view);
		listView.setAdapter(adapter);
		adapter.notifyDataSetChanged();
	}
	
	protected void add() {
		// Set up an animal with the userName specified
		Animal animal = new Animal();
		animal.setUserName(userName);
		
		Intent editAnimalActivity = new Intent(getApplicationContext(), EditAnimalActivity.class);
		editAnimalActivity.putExtra(getString(R.string.extra_animal_object), animal);
		startActivityForResult(editAnimalActivity, ADD_ANIMAL_ACTIVITY);
	}
	
	protected void view(Object object) {
		Animal selectedAnimal = (Animal)object;
		
		Intent viewAnimalActivity = new Intent(getApplicationContext(), ViewAnimalActivity.class);
		viewAnimalActivity.putExtra(getString(R.string.extra_animal_object), selectedAnimal);
		
		startActivityForResult(viewAnimalActivity, VIEW_ANIMAL_ACTIVITY);
	}

	@Override
	protected void onSaveInstanceState(Bundle savedInstanceState) {
		super.onSaveInstanceState(savedInstanceState);
		
		savedInstanceState.putString(
							getString(R.string.extra_user_name), userName);
	}
	
	@Override
	protected void onPause() {
		super.onPause();
		
		// Save the userName
		SharedPreferences settings = getSharedPreferences(
										getString(R.string.prefs_animal_list),
										Context.MODE_PRIVATE);
		SharedPreferences.Editor editor = settings.edit();
		editor.putString(getString(R.string.extra_user_name), userName);
		editor.commit();
		
		onSaveInstanceState(new Bundle());
	}
	
	@Override
	protected void onResume() {
		super.onResume();
		
		// Retrieve the userName
		SharedPreferences settings = getSharedPreferences(
										getString(R.string.prefs_animal_list),
										Context.MODE_PRIVATE);
		if(TextUtils.isEmpty(userName)) {
			userName = settings.getString(getString(R.string.extra_user_name), "");
		}
	}
	
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.animal_list, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		// Handle action bar item clicks here. The action bar will
		// automatically handle clicks on the Home/Up button, so long
		// as you specify a parent activity in AndroidManifest.xml.
		switch(item.getItemId()) {
			default :
				return super.onOptionsItemSelected(item);
		}
	}
	
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);
		
		if(requestCode == VIEW_ANIMAL_ACTIVITY &&
			(resultCode == ResultUtil.EDITED ||
			 resultCode == ResultUtil.DELETED)) {
			retrieveList();
			populateList();
		}
		else if(requestCode == ADD_ANIMAL_ACTIVITY &&
				resultCode == ResultUtil.RESULT_SUCCESS) {
			retrieveList();
			populateList();
		}
	}
}
